import axios from '../utils/axios';
import type { TaskRequest, Task } from './task';

export interface ProjectEvaluation {
  id: number;
  projectId: number;
  projectTitle: string;
  score: number;
  comment: string;
  evaluatedBy: number;
  evaluatorName: string;
  evaluationTime: string;
}

export interface Project {
  id: number;
  title: string;
  description?: string;
  category?: string;
  requirements?: string;
  resources?: string;
  status: string;
  startTime?: string;
  endTime?: string;
  supervisorId: number;
  assigneeId?: number;
  assigneeName?: string;
  createTime?: string;
  updateTime?: string;
  taskRequest?: TaskRequest;
  tasks?: Task[];
}

/**
 * Gets all projects for a supervisor.
 * @param supervisorId The ID of the supervisor.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getSupervisorProjects = async (supervisorId: number) => {
  const response = await axios.get(`/api/supervisor/projects?supervisorId=${supervisorId}`);
  return response.data;
};

/**
 * Gets projects for a supervisor with a specific status.
 * @param supervisorId The ID of the supervisor.
 * @param status The status of the projects to retrieve.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getSupervisorProjectsByStatus = async (supervisorId: number, status: string) => {
  const response = await axios.get(`/api/supervisor/projects/status/${status}?supervisorId=${supervisorId}`);
  return response.data;
};

/**
 * Gets the details of a project.
 * @param projectId The ID of the project.
 * @returns A promise that resolves to a Project object.
 */
export const getProjectDetail = async (projectId: number) => {
  const response = await axios.get(`/api/supervisor/projects/${projectId}`);
  return response.data;
};

/**
 * Creates a new project.
 * @param projectData The data for the new project.
 * @returns A promise that resolves to a Project object.
 */
export const createProject = async (projectData: Partial<Project>) => {
  const response = await axios.post('/api/supervisor/projects', projectData);
  return response.data;
};

/**
 * Updates an existing project.
 * @param projectId The ID of the project to update.
 * @param projectData The data to update the project with.
 * @returns A promise that resolves to a Project object.
 */
export const updateProject = async (projectId: number, projectData: Partial<Project>) => {
  const response = await axios.put(`/api/supervisor/projects/${projectId}`, projectData);
  return response.data;
};

/**
 * Deletes a project.
 * @param projectId The ID of the project to delete.
 * @returns A promise that resolves to a boolean indicating whether the deletion was successful.
 */
export const deleteProject = async (projectId: number) => {
  const response = await axios.delete(`/api/supervisor/projects/${projectId}`);
  return response.status === 200;
};

/**
 * Assigns a project to a student.
 * @param projectId The ID of the project to assign.
 * @param studentId The ID of the student to assign the project to.
 * @returns A promise that resolves to a Project object.
 */
export const assignProjectToStudent = async (projectId: number, studentId: number) => {
  const response = await axios.put(`/api/supervisor/projects/${projectId}/assign/${studentId}`);
  return response.data;
};

/**
 * Updates the status of a project.
 * @param projectId The ID of the project to update.
 * @param status The new status for the project.
 * @returns A promise that resolves to a Project object.
 */
export const updateProjectStatus = async (projectId: number, status: string) => {
  const response = await axios.put(`/api/supervisor/projects/${projectId}/status`, { status });
  return response.data;
};

/**
 * Gets projects by category.
 * @param category The category to filter projects by.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getProjectsByCategory = async (category: string) => {
  const response = await axios.get(`/api/supervisor/projects/category/${category}`);
  return response.data;
};

/**
 * Gets projects for a student.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getStudentProjects = async () => {
  const response = await axios.get(`/api/user/projects`);
  return response.data;
};

/**
 * Gets projects by priority.
 * @param priority The priority to filter projects by.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getProjectsByPriority = async (priority: string) => {
  const response = await axios.get(`/api/supervisor/projects/priority/${priority}`);
  return response.data;
};

/**
 * Gets all project categories.
 * @returns A promise that resolves to an array of project categories.
 */
export const getAllProjectCategories = async () => {
  const response = await axios.get('/api/supervisor/projects/categories');
  return response.data;
};

/**
 * Allows a student to apply for a project.
 * @param projectData The data for the project application.
 * @returns A promise that resolves to a Project object.
 */
export const applyForProject = async (projectData: Partial<Project>) => {
  // Ensure data format is correct
  const data = {
    ...projectData,
    // If there are tasks, make sure the format is correct
    tasks: projectData.tasks ? projectData.tasks.map(task => ({
      ...task,
      // Make sure the necessary fields exist
      supervisorId: projectData.supervisorId,
      // Use the current time if startTime is not set
      startTime: task.startTime || new Date().toISOString(),
      // Make sure the status is set correctly
      status: task.status || 'Not Started' // Not Started
    })) : []
  };

  const response = await axios.post('/api/user/projects/apply', data);
  return response.data;
};

/**
 * Gets pending project applications for a supervisor.
 * @param supervisorId The ID of the supervisor.
 * @returns A promise that resolves to an array of Project objects.
 */
export const getPendingReviewProjects = async (supervisorId: number) => {
  const response = await axios.get(`/api/supervisor/projects/pending-review?supervisorId=${supervisorId}`);
  return response.data;
};

/**
 * Allows a supervisor to review a project application.
 * @param projectId The ID of the project to review.
 * @param approved Whether the application was approved or not.
 * @returns A promise that resolves to a Project object.
 */
export const reviewProjectApplication = async (projectId: number, approved: boolean) => {
  const response = await axios.put(`/api/supervisor/projects/${projectId}/review`, {
    approved
  });
  return response.data;
};

// ==================== Project Evaluation Interface ====================

/**
 * Creates or updates a project evaluation (supervisor view).
 * @param projectId The ID of the project to evaluate.
 * @param score The score for the project.
 * @param comment The comment for the project.
 * @returns A promise that resolves to a ProjectEvaluation object.
 */
export const evaluateProject = async (projectId: number, score: number, comment: string): Promise<ProjectEvaluation> => {
  const response = await axios.post<ProjectEvaluation>(`/api/supervisor/projects/${projectId}/evaluate`, { score, comment });
  return response.data;
};

/**
 * Gets a project evaluation (supervisor view).
 * @param projectId The ID of the project to get the evaluation for.
 * @returns A promise that resolves to a ProjectEvaluation object.
 */
export const getProjectEvaluation = async (projectId: number): Promise<ProjectEvaluation> => {
  const response = await axios.get<ProjectEvaluation>(`/api/supervisor/projects/${projectId}/evaluation`);
  return response.data;
};

/**
 * Deletes a project evaluation (supervisor view).
 * @param projectId The ID of the project to delete the evaluation for.
 * @returns A promise that resolves to a boolean indicating whether the deletion was successful.
 */
export const deleteProjectEvaluation = async (projectId: number): Promise<boolean> => {
  const response = await axios.delete(`/api/supervisor/projects/${projectId}/evaluation`);
  return response.status === 200;
};

/**
 * Gets a project evaluation (student view).
 * @param projectId The ID of the project to get the evaluation for.
 * @returns A promise that resolves to a ProjectEvaluation object.
 */
export const getMyProjectEvaluation = async (projectId: number): Promise<ProjectEvaluation> => {
  const response = await axios.get<ProjectEvaluation>(`/api/user/projects/${projectId}/evaluation`);
  return response.data;
};

/**
 * Updates the status of a project to "Waiting for Review".
 * @param projectId The ID of the project to submit for review.
 * @returns A promise that resolves to a Project object.
 */
export const submitProjectForReview = async (projectId: number): Promise<Project> => {
  const response = await axios.put(`/api/user/projects/${projectId}/submit-for-review`);
  return response.data;
};